#include "vanila/native.h"
#include "vanila/dsobject.h"
#include "vanila/virtualmachine.h"
#include "vanila/allocator.h"
#include "vanila/allocator.h"

namespace vanila
{

Value Native::DataStructure::listInit(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 1, "list.init");

    ObjectInstance* instance = args[0].asInstance();
    ObjectList* list = Native::allocator->allocateList();
    instance->setObject(list);

    return Value(instance);
}

Value Native::DataStructure::listAppend(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 2, "list.append");

    ObjectInstance* instance = args[0].asInstance();
    ObjectList* list = instance->object()->asList();
    list->append(args[1]);

    return Value(ValueType::NIL);
}

Value Native::DataStructure::listInsert(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 3, "list.insert");

    ObjectInstance* instance = args[0].asInstance();
    ObjectList* list = instance->object()->asList();
    bool res = list->insert(args[1].integer(), args[2]);

    return Value(res);
}

Value Native::DataStructure::listPop(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 2, "list.pop");

    ObjectInstance* instance = args[0].asInstance();
    ObjectList* list = instance->object()->asList();
    bool res = list->pop(args[1].integer());

    return Value(res);
}

Value Native::DataStructure::dictInit(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 1, "dict.init");

    ObjectInstance* instance = args[0].asInstance();
    ObjectDictionary* dict = Native::allocator->allocateDictionary();
    instance->setObject(dict);

    return Value(instance);
}

Value Native::DataStructure::dictAdd(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 3, "dict.add");

    ObjectInstance* instance = args[0].asInstance();
    ObjectDictionary* dict = instance->object()->asDictionary();
    dict->add(args[1], args[2]);

    return Value(ValueType::NIL);
}

Value Native::DataStructure::dictGet(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 2, "dict.get");

    ObjectInstance* instance = args[0].asInstance();
    ObjectDictionary* dict = instance->object()->asDictionary();

    Value value;
    if(dict->get(args[1], value))
        return value;

    return Value(ValueType::NIL);
}

Value Native::DataStructure::setInit(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 1, "dict.init");

    ObjectInstance* instance = args[0].asInstance();
    ObjectSet* set = Native::allocator->allocateSet();
    instance->setObject(set);

    return Value(instance);
}

Value Native::DataStructure::setAdd(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 2, "set.add");

    ObjectInstance* instance = args[0].asInstance();
    ObjectSet* set = instance->object()->asSet();
    set->add(args[1]);

    return Value(ValueType::NIL);
}

Value Native::DataStructure::setContain(uint32_t argCount, Value* args)
{
    Native::assertArgumentCount(argCount, 2, "set.add");

    ObjectInstance* instance = args[0].asInstance();
    ObjectSet* set = instance->object()->asSet();

    return Value(set->contain(args[1]));
}

}